﻿using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Collections.Generic;
using Microsoft.SharePoint.Utilities;
using SharePointListSecurity.Model;
using SharePointListSecurity.WebControls;
using System.Linq;
using SharePointListSecurity.Data;

namespace SharePointListSecurity.Layouts.SharePointListSecurity
{
    public partial class EditListColumnPermissions : LayoutsPageBase
    {
        protected SPList spList;
        protected SPField spField;
        protected SPListSecurityContextDataContext context;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (Request.HttpMethod == "POST")
                SPUtility.ValidateFormDigest();

            bool hasFullControl = SPContext.Current.Web.AllRolesForCurrentUser.Contains(SPContext.Current.Web.RoleDefinitions["Full Control"]);
            if (hasFullControl)
            {
                context = new SPListSecurityContextDataContext(this.Web.Site.Url);

                string[] strLists = Request.QueryString.GetValues("List");
                if (strLists == null || strLists.Length < 1)
                {
                    throw new SPException(SPResource.GetString(Strings.MissingRequiredQueryString, "List"));
                }
                string[] strField = Request.QueryString.GetValues("Field");
                if (strField == null || strField.Length < 1)
                {
                    throw new SPException(SPResource.GetString(Strings.MissingRequiredQueryString, "Field"));
                }
                spList = this.Web.Lists.GetList(new Guid(strLists[0]), true);
                spField = spList.Fields[new Guid(strField[0])];

                if (!Page.IsPostBack)
                {
                    DisplayFormFieldsPermissions displayPermissions = context.DisplayFormFieldsPermissions
                                                                                .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                                                                && new Guid(p.ColumnID) == spField.Id);
                    EditFormFieldsPermissions editPermissions = context.EditFormFieldsPermissions
                                                                                .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                                                                && new Guid(p.ColumnID) == spField.Id);
                    AddFormFieldsPermissions addPermissions = context.AddFormFieldsPermissions
                                                                                .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                                                                && new Guid(p.ColumnID) == spField.Id);
                    UsersAndGroupsManager usersAndGroupsManager = new UsersAndGroupsManager(this.Web);
                    if (displayPermissions != null)
                    {
                        if (!String.IsNullOrEmpty(displayPermissions.Permission))
                            ddlDisplayPermissions.SelectedValue = displayPermissions.Permission;
                        List<string> usersAndGroupsLoginNames = usersAndGroupsManager.GetLoginNames(displayPermissions.UsersAndGroups, displayPermissions.UsersAndGroupsId);
                        pplDisplayPermissions.CommaSeparatedAccounts = String.Join(",", usersAndGroupsLoginNames.ToArray());
                    }

                    if (editPermissions != null)
                    {
                        if (!String.IsNullOrEmpty(editPermissions.Permission))
                            ddlEditPermissions.SelectedValue = editPermissions.Permission;
                        List<string> editFormUsersAndGroupsLoginNames = usersAndGroupsManager.GetLoginNames(editPermissions.UsersAndGroups, editPermissions.UsersAndGroupsId);
                        pplEditPermissions.CommaSeparatedAccounts = String.Join(",", editFormUsersAndGroupsLoginNames.ToArray());

                        if (!String.IsNullOrEmpty(editPermissions.DisplayMode))
                            ddlEditDisplayMode.SelectedValue = editPermissions.DisplayMode;
                        List<string> editDisplayUsersAndGroupsLoginNames = usersAndGroupsManager.GetLoginNames(editPermissions.DisplayModeUsersAndGroups, editPermissions.DisplayModeUsersAndGroupsId);
                        pplEditDisplayMode.CommaSeparatedAccounts = String.Join(",", editDisplayUsersAndGroupsLoginNames.ToArray());
                    }

                    if (addPermissions != null)
                    {
                        if (!String.IsNullOrEmpty(addPermissions.Permission))
                            ddlAddPermissions.SelectedValue = addPermissions.Permission;
                        List<string> newFormUsersAndGroupsLoginNames = usersAndGroupsManager.GetLoginNames(addPermissions.UsersAndGroups, addPermissions.UsersAndGroupsId);
                        pplAddPermissions.CommaSeparatedAccounts = String.Join(",", newFormUsersAndGroupsLoginNames.ToArray());
                    }
                }
            }
            else
            {
                Response.Redirect(this.Web.Url + "/_layouts/accessdenied.aspx");
            }
        }

        protected void DeltePermissions_Click(object sender, EventArgs e)
        {
            ResetPermissions();
            Response.Redirect(this.Web.Url + String.Format("/_layouts/sharePointlistSecurity/listcolumnpermissions.aspx?List={0}", spList.ID.ToString()));
        }

        protected void SavePermissions_Click(object sender, EventArgs e)
        {
            ResetPermissions();

            if (ddlDisplayPermissions.SelectedValue != PermissionType.HideField || !String.IsNullOrEmpty(pplDisplayPermissions.CommaSeparatedAccounts))
            {
                var displayPermissions = new DisplayFormFieldsPermissions();
                displayPermissions.ListID = spList.ID.ToString();
                displayPermissions.ColumnID = spField.Id.ToString();
                displayPermissions.Permission = ddlDisplayPermissions.SelectedValue;
                var x = pplDisplayPermissions.CommaSeparatedAccounts.Split(',')
                                                                    .Where(a => !String.IsNullOrEmpty(a))
                                                                    .ToList();

                displayPermissions.UsersAndGroupsId = pplDisplayPermissions.CommaSeparatedAccounts.Split(',')
                                                                           .Where(a => !String.IsNullOrEmpty(a))
                                                                           .Select(a => GetUserIdFromName(a))
                                                                           .ToList();
                context.DisplayFormFieldsPermissions.InsertOnSubmit(displayPermissions);
                context.SubmitChanges();
            }

            if (ddlEditPermissions.SelectedValue != PermissionType.HideField || !String.IsNullOrEmpty(pplEditPermissions.CommaSeparatedAccounts)
                || ddlEditDisplayMode.SelectedValue != PermissionType.ReadOnly || !String.IsNullOrEmpty(pplEditDisplayMode.CommaSeparatedAccounts))
            {
                var editPermissions = new EditFormFieldsPermissions();
                editPermissions.ListID = spList.ID.ToString();
                editPermissions.ColumnID = spField.Id.ToString();
                editPermissions.Permission = ddlEditPermissions.SelectedValue;
                editPermissions.UsersAndGroupsId = pplEditPermissions.CommaSeparatedAccounts.Split(',')
                                                                           .Where(a => !String.IsNullOrEmpty(a))
                                                                           .Select(a => GetUserIdFromName(a))
                                                                           .ToList();
                editPermissions.DisplayMode = ddlEditDisplayMode.SelectedValue;
                editPermissions.DisplayModeUsersAndGroupsId = pplEditDisplayMode.CommaSeparatedAccounts.Split(',')
                                                                                .Where(a => !String.IsNullOrEmpty(a))
                                                                                .Select(a => GetUserIdFromName(a))
                                                                                .ToList();

                context.EditFormFieldsPermissions.InsertOnSubmit(editPermissions);
                context.SubmitChanges();
            }

            if (ddlAddPermissions.SelectedValue != PermissionType.HideField || !String.IsNullOrEmpty(pplAddPermissions.CommaSeparatedAccounts))
            {
                var addPermissions = new AddFormFieldsPermissions();
                addPermissions.ListID = spList.ID.ToString();
                addPermissions.ColumnID = spField.Id.ToString();
                addPermissions.Permission = ddlAddPermissions.SelectedValue;
                addPermissions.UsersAndGroupsId = pplAddPermissions.CommaSeparatedAccounts.Split(',')
                                                                           .Where(a => !String.IsNullOrEmpty(a))
                                                                           .Select(a => GetUserIdFromName(a))
                                                                           .ToList();
                context.AddFormFieldsPermissions.InsertOnSubmit(addPermissions);
                context.SubmitChanges();
            }
            Response.Redirect(this.Web.Url + String.Format("/_layouts/sharePointlistSecurity/listcolumnpermissions.aspx?List={0}", spList.ID.ToString()));
        }

        private int? GetUserIdFromName(string name)
        {
            var group = Web.SiteGroups.Cast<SPGroup>()
                                    .FirstOrDefault(g => g.LoginName == name);

            if (group != null)
                return (int?)group.ID;

            var user = Web.EnsureUser(name);
            return (int?)user.ID;
        }

        private void ResetPermissions()
        {
            var displayPermissions = context.DisplayFormFieldsPermissions
                                            .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                            && new Guid(p.ColumnID) == spField.Id);
            if (displayPermissions != null)
                context.DisplayFormFieldsPermissions.DeleteOnSubmit(displayPermissions);

            var editPermissions = context.EditFormFieldsPermissions
                                         .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                        && new Guid(p.ColumnID) == spField.Id);
            if (editPermissions != null)
                context.EditFormFieldsPermissions.DeleteOnSubmit(editPermissions);

            var addPermissions = context.AddFormFieldsPermissions
                                        .FirstOrDefault(p => new Guid(p.ListID) == spList.ID
                                                        && new Guid(p.ColumnID) == spField.Id);
            if (addPermissions != null)
                context.AddFormFieldsPermissions.DeleteOnSubmit(addPermissions);

            context.SubmitChanges();
        }
    }
}
